package com.css.bjdt_core.reportExplainFill.service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.css.bjdt_core.explain.entity.RptTemplateExplain;
import com.css.bjdt_core.explain.service.ReportTemplateExplainService;
import com.css.bjdt_core.explain.service.RptCellExplainService;
import com.css.bjdt_core.reportExplainFill.entity.ReportExplainFillEntity;
import com.css.bjdt_core.reportExplainFill.entity.ReportExplainTextFillEntity;
import com.css.bjdt_core.reportPrepare.entity.RptUnit;
import com.css.bjdt_core.reportPrepare.entity.RptUnitAnnualRel;
import com.css.bjdt_core.reportPrepare.service.RptUnitService;
import com.css.bjdt_core.util.CommonUtil;
import com.css.bjdt_core.util.ExecutorPool;
import com.css.bjdt_core.util.ReportConstant;

@Service
//报表说明汇总方法重写
public class RptCellExplainSummaryNewService {

	/*int cpuNum = Runtime.getRuntime().availableProcessors();
	ExecutorService fixedThreadPoolExplain = Executors.newFixedThreadPool(cpuNum);*/
	@Autowired
	private Dao dao;

	@Autowired
	private ReportTemplateExplainService reportTemplateExplainService;

	@Autowired
	private RptExplainCellFillService rptExplainCellFillService;

	@Autowired
	private RptCellExplainService rptCellExplainService;

	@Autowired
	private RptUnitService rptUnitService;

	private static final Log logger = LogFactory.getLog(RptCellExplainSummaryNewService.class);

	public Map<String, List> reporExplainValueSummary(HttpSession session, List<String> templateIdList,
			List<String> treadExplainDzzIdList, String annualId, String dzzId) {
		ExecutorService pool = ExecutorPool.getInstance().getPool();
		List<ReportExplainFillEntity> reportExplainFillEntityList = new ArrayList<ReportExplainFillEntity>();
		List<ReportExplainTextFillEntity> reportExplainTextFillEntityList = new ArrayList<ReportExplainTextFillEntity>();
		List<ReporExplainValueSummaryTread> tasks = new ArrayList<ReporExplainValueSummaryTread>();
		for (String templateId : templateIdList) {
			ReporExplainValueSummaryTread reporExplainValueSummaryTread = new ReporExplainValueSummaryTread(session,
					treadExplainDzzIdList, annualId, dzzId, templateId);
			tasks.add(reporExplainValueSummaryTread);
		}
		try {
			List<Future<Map<Integer, Object>>> res = pool.invokeAll(tasks);
			for (Future<Map<Integer, Object>> fu : res) {
				Map<Integer, Object> result = fu.get();
				reportExplainFillEntityList.addAll((Collection<ReportExplainFillEntity>) result.get(1));
				reportExplainTextFillEntityList.addAll((Collection<ReportExplainTextFillEntity>) result.get(2));
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/*for (String key : reportExplainDataMap.keySet()) {
			ReportExplainFillEntity reportExplainFillEntity = reportExplainDataMap.get(key);
			reportExplainFillEntityList.add(reportExplainFillEntity);
		}
		for (String key : reportExplainTextDataMap.keySet()) {
			ReportExplainTextFillEntity reportExplainTextFillEntity = reportExplainTextDataMap.get(key);
			reportExplainTextFillEntityList.add(reportExplainTextFillEntity);
		}*/
		/*rptExplainCellFillService.insertExplainCellValueList(annualId, reportExplainFillEntityList);
		rptExplainCellFillService.insertExplainCellTextValueList(annualId, reportExplainTextFillEntityList);*/
		/*System.out.println(reportExplainDataMap);
		System.out.println(reportExplainTextDataMap);*/
		Map<String, List> resultMap = new HashMap<String, List>();
		resultMap.put("reportExplainFillEntityList", reportExplainFillEntityList);
		resultMap.put("reportExplainTextFillEntityList", reportExplainTextFillEntityList);
		//System.out.println(reportExplainFillEntityList);
		//System.out.println(reportExplainTextFillEntityList);
		return resultMap;
	}

	/**
	 * 汇总报表说明批注。条目型批注
	 * @param dzzIdList 需要汇总的党组织集合
	 * @param explainIdList 需要汇总的报表说明
	 * @param annualId 年度ID
	 * @param summaryDzzId 汇到哪个党组织下
	 */
	public void rptCellExplainSummaryTiaoMu(final List<String> dzzIdList, final List<String> explainIdList, String annualId,
											final String summaryDzzId, List<ReportExplainFillEntity> reportExplainDataList) {

		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;

		String sqlStr = "SELECT a.EXPLAIN_CELL_VALUE, a.ABS_ROW_NUM, a.ABS_COL_NUM, a.DZZ_ID, a.EXPLAIN_ID " +
				"FROM $tableName a, RPT_UNIT_ANNUAL_R b, RPT_UNIT c WHERE a.DZZ_ID = b.DZZ_ID and c.ID = b.UNIT_ID and a.DZZ_ID in ( $dzzIdList ) and " +
				"a.EXPLAIN_ID in ( $explainIdList ) and " +
				"b.ANNUAL_ID = @annual_id AND ((SUM_STATUS IS NULL and c.UNITTYPE = '1') or (SUM_STATUS = 1 and c.UNITTYPE <> '1')) AND ABS_ROW_NUM != 2";

		String strDzzIds = CommonUtil.convertIDList(dzzIdList);
		String explainIds = CommonUtil.convertIDList(explainIdList);

		String sqlNewStr = sqlStr.replace("$tableName", tableName)
				.replace("$dzzIdList", strDzzIds).replace("$explainIdList", explainIds);
		Sql sql = Sqls.create(sqlNewStr);
		sql.params().set("annual_id", annualId);
		sql.setCallback(new SqlCallback() {

			public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
				Map<String, Map<String, List<ReportExplainFillEntity>>> res = new HashMap<>();
				while (rs.next()) {
					ReportExplainFillEntity entity = new ReportExplainFillEntity();
					entity.setExplainId(rs.getString("EXPLAIN_ID"));
					entity.setAbsColNum(rs.getString("ABS_COL_NUM"));
					entity.setAbsRowNum(rs.getString("ABS_ROW_NUM"));
					entity.setDzzId(summaryDzzId);
					entity.setExplainCellValue(rs.getString("EXPLAIN_CELL_VALUE"));
					entity.setExplainCellDataId(CommonUtil.getUUID());
					entity.setIsSameRow(rs.getString("DZZ_ID"));
					entity.setSumStatus("1");

					if(res.containsKey(entity.getExplainId())) {
						Map<String, List<ReportExplainFillEntity>> dzzMap = res.get(entity.getExplainId());
						if(dzzMap.containsKey(entity.getIsSameRow())) {
							List<ReportExplainFillEntity> enList = dzzMap.get(entity.getIsSameRow());
							enList.add(entity);
						} else {
							List<ReportExplainFillEntity> enList = new ArrayList<>();
							enList.add(entity);
							dzzMap.put(entity.getIsSameRow(), enList);
						}
					} else {
						Map<String, List<ReportExplainFillEntity>> dzzMap = new HashMap<>();
						List<ReportExplainFillEntity> enList = new ArrayList<>();
						enList.add(entity);
						dzzMap.put(entity.getIsSameRow(), enList);
						res.put(entity.getExplainId(), dzzMap);
					}

				}
				return res;
			}
		});
		dao.execute(sql);
		Map<String, Map<String, List<ReportExplainFillEntity>>> resMap = sql.getObject(Map.class);

		String rowRangeSql = "SELECT min(to_number(abs_row_num)) min_abs_row, max(to_number(abs_row_num)) max_abs_row, a.DZZ_ID, a.EXPLAIN_ID " +
				"FROM $tableName a, RPT_UNIT_ANNUAL_R b, RPT_UNIT c WHERE a.DZZ_ID = b.DZZ_ID and c.ID = b.UNIT_ID and a.DZZ_ID in ( $dzzIdList ) and " +
				"a.EXPLAIN_ID in ( $explainIdList ) and " +
				"b.ANNUAL_ID = @annual_id AND ((SUM_STATUS IS NULL and c.UNITTYPE = '1') or (SUM_STATUS = 1 and c.UNITTYPE <> '1')) AND ABS_ROW_NUM != 2 " +
				"GROUP BY a.DZZ_ID, a.EXPLAIN_ID";

		Sql sqlforRange = Sqls.create(rowRangeSql.replace("$tableName", tableName)
				.replace("$dzzIdList", strDzzIds)
				.replace("$explainIdList", explainIds));
		sqlforRange.params().set("annual_id", annualId);
		sqlforRange.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
				Map<String, Map<String, List<Integer>>> resRow = new HashMap<>();
				while (rs.next()) {
					int minRow = rs.getInt("min_abs_row");
					int maxRow = rs.getInt("max_abs_row");
					String dzzid = rs.getString("DZZ_ID");
					String explainid = rs.getString("EXPLAIN_ID");
					Map<String, List<Integer>> dzzMap;
					if(resRow.containsKey(explainid)) {
						dzzMap = resRow.get(explainid);
					} else {
						dzzMap = new HashMap<>();
						resRow.put(explainid, dzzMap);
					}
					List<Integer> rowList = new ArrayList<>();
					rowList.add(minRow);
					rowList.add(maxRow);
					dzzMap.put(dzzid, rowList);
				}
				return resRow;
			}
		});
		dao.execute(sqlforRange);
		Map<String, Map<String, List<Integer>>> resRow = sqlforRange.getObject(Map.class);

		for (String explainId : explainIdList) {
			int num = 0;
			Map<String, List<ReportExplainFillEntity>> datMap = resMap.get(explainId);
			Map<String, List<Integer>> rowMap = resRow.get(explainId);
			if(datMap == null || rowMap == null) {
				continue;
			}
			for (String dzzId : dzzIdList) {
				Map<String, String> mapRow = new HashMap<>();
				List<ReportExplainFillEntity> list = datMap.get(dzzId);
				List<Integer> rows = rowMap.get(dzzId);
				if(list == null || rows == null) {
					continue;
				}
				int minRow = rows.get(0);
				int maxRow = rows.get(1);
				if (minRow != 0) {
					//Integer differenceRow = maxRow - minRow;
					int rowNew = minRow + num;
					for (int a = minRow; a <= maxRow; a++) {
						mapRow.put(a + "", rowNew + "");
						rowNew++;
					}
				}
				for (ReportExplainFillEntity reportExplainFillEntity : list) {
					reportExplainFillEntity.setAbsRowNum(mapRow.get(reportExplainFillEntity.getAbsRowNum()));

				}
				reportExplainDataList.addAll(list);
				num = num + mapRow.size();
			}
		}
		//rptExplainCellFillService.insertExplainCellValueList(annualId, reportExplainFillEntityList);
	}

	public Map<String, String> getRowMap(String annualId, String dzzId, String explainId, Integer num, boolean isSum) {
		Map<String, String> mapRow = new HashMap<String, String>();
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String strMinSql = "select min(to_number(abs_row_num)) from " + tableName
				+ " where explain_id = @explainId and dzz_id = @dzzId and ABS_ROW_NUM != 2 and "
				+ (isSum ? "sum_status = 1" : "sum_status is null");
		String strMaxSql = "select max(to_number(abs_row_num)) from " + tableName
				+ " where explain_id = @explainId and dzz_id = @dzzId and ABS_ROW_NUM != 2 and "
				+ (isSum ? "sum_status = 1" : "sum_status is null");
		Sql sqlMin = Sqls.create(strMinSql);
		Sql sqlMax = Sqls.create(strMaxSql);
		sqlMin.params().set("explainId", explainId).set("dzzId", dzzId);
		sqlMax.params().set("explainId", explainId).set("dzzId", dzzId);
		sqlMin.setCallback(Sqls.callback.integer());
		sqlMax.setCallback(Sqls.callback.integer());
		dao.execute(sqlMin);
		dao.execute(sqlMax);
		int minRow = sqlMin.getObject(Integer.class);
		int maxRow = sqlMax.getObject(Integer.class);
		if (minRow == 0) {
			return mapRow;
		} else {
			//Integer differenceRow = maxRow - minRow;
			int rowNew = minRow + num;
			for (int a = minRow; a <= maxRow; a++) {
				mapRow.put(a + "", rowNew + "");
				rowNew++;
			}
			return mapRow;
		}
	}

	public int getCountByDzzIdAndExplainId(String annualId, String dzzId, String explainId) {
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String sqlStr = "select count(*) from (SELECT abs_row_num FROM " + tableName
				+ " where EXPLAIN_ID = @explainId and DZZ_ID = @dzzId and SUM_STATUS is null GROUP BY abs_row_num) t";
		Sql sql = Sqls.create(sqlStr);
		sql.params().set("dzzId", dzzId).set("explainId", explainId);
		sql.setCallback(Sqls.callback.integer());
		dao.execute(sql);
		return sql.getObject(Integer.class);
	}

	//删除已经汇总过的数据，方便重新汇总
	public void deleteByDzzIdAnIsSummary(String dzzId, String annualId) {
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String strSql = ReportConstant.EXPLAIN_DELETE_SUMMARY_SQL.replace("$table_name", tableName);
		Sql sql = Sqls.create(strSql);
		sql.params().set("DZZ_ID", dzzId);
		dao.execute(sql);
	}

	/**
	 * 汇总报表说明批注。数字型批注
	 * @param dzzIdList 需要汇总的党组织集合
	 * @param explainIdList 需要汇总的报表说明
	 * @param annualId 年度ID
	 * @param summaryDzzId 汇到哪个党组织下
	 */

	public void rptCellExplainSummaryShuZi(List<String> dzzIdList, List<String> explainIdList, String annualId,
			final String summaryDzzId, final List<ReportExplainFillEntity> reportExplainDataMap) {
		String strDzzId = CommonUtil.convertIDList(dzzIdList);
		String explainId = CommonUtil.convertIDList(explainIdList);

		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String strSql = "select sum(EXPLAIN_CELL_VALUE) value,EXPLAIN_ID, ABS_ROW_NUM, ABS_COL_NUM from " + tableName
				+ " where " + "DZZ_ID in (" + strDzzId + ") and " + "EXPLAIN_ID in (" + explainId + ") "
				/*+ (isSum ? "sum_status = 1" : "sum_status is null")*/
				+ "group by EXPLAIN_ID, ABS_ROW_NUM, ABS_COL_NUM";
		Sql sql = Sqls.create(strSql);
		sql.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
				while (rs.next()) {
					ReportExplainFillEntity reportExplainFillEntity = new ReportExplainFillEntity();
					reportExplainFillEntity.setExplainId(CommonUtil.getUUID());
					reportExplainFillEntity.setAbsColNum(rs.getString("ABS_COL_NUM"));
					reportExplainFillEntity.setAbsRowNum(rs.getString("ABS_ROW_NUM"));
					reportExplainFillEntity.setExplainCellValue(rs.getString("value"));
					reportExplainFillEntity.setDzzId(summaryDzzId);
					reportExplainFillEntity.setSumStatus("1");
					reportExplainFillEntity.setExplainId(rs.getString("EXPLAIN_ID"));
					reportExplainFillEntity.setIsSameRow(summaryDzzId);

					reportExplainDataMap.add(reportExplainFillEntity);
				}
				return null;
			}
		});
		dao.execute(sql);
	}

	/**
	 * 汇总报表说明批注。文本型批注
	 * @param dzzIdList 需要汇总的党组织集合
	 * @param explainIdList 需要汇总的报表说明
	 * @param annualId 年度ID
	 * @param summaryDzzId 汇到哪个党组织下
	 */

	public void rptCellExplainSummaryWenBen(List<String> dzzIdList, List<String> explainIdList, String annualId,
			final String summaryDzzId, final List<ReportExplainFillEntity> reportExplainDataMap,
			final List<ReportExplainTextFillEntity> reportExplainTextDataMap) {
		/*List<ReportExplainFillEntity> reportExplainFillEntityList = new ArrayList<ReportExplainFillEntity>();
		List<ReportExplainTextFillEntity> reportExplainTextFillEntityList = new ArrayList<ReportExplainTextFillEntity>();*/
		String strDzzId = CommonUtil.convertIDList(dzzIdList);
		String explainId = CommonUtil.convertIDList(explainIdList);
		String tableName = ReportConstant.EXPLAIN_TABLE_PREFIX + annualId;
		String tableNameText = ReportConstant.EXPLAIN_TEXT_TABLE_PREFIX + annualId;
		String strSql = "SELECT "
				+ "listagg(B.EXPLAIN_TEXT, ',') within GROUP (order by B.EXPLAIN_TEXT) as EXPLAIN_VALUE, "
				+ "A .EXPLAIN_ID, A .ABS_COL_NUM, A .ABS_ROW_NUM FROM " + tableName + " A, " + tableNameText
				+ " B WHERE A.EXPLAIN_CELL_VALUE = B.EXPLAIN_TEXT_ID " + " AND A.EXPLAIN_ID IN (" + explainId + ")"
				+ " AND A.DZZ_ID IN ( " + strDzzId + ") " /*+ (isSum ? "a.sum_status = 1" : "a.sum_status is null")*/
				+ " group by A.EXPLAIN_ID, A.ABS_COL_NUM, A.ABS_ROW_NUM";

		Sql sql = Sqls.create(strSql);
		sql.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
				while (rs.next()) {

					ReportExplainTextFillEntity reportExplainTextFillEntity = new ReportExplainTextFillEntity();
					String explainCellValueId = CommonUtil.getUUID();
					reportExplainTextFillEntity.setExplainCellValueId(explainCellValueId);
					String value = rs.getString("EXPLAIN_VALUE");
					if (!value.isEmpty()) {
						//logger.error("rptCellExplainSummaryWenBen, str: " + str);
						reportExplainTextFillEntity.setExplainCellText(value);
					}
					reportExplainTextFillEntity.setDzzId(summaryDzzId);
					reportExplainTextFillEntity.setExplainId(rs.getString("EXPLAIN_ID"));
					//reportExplainTextFillEntityList.add(reportExplainTextFillEntity);
					reportExplainTextDataMap.add(reportExplainTextFillEntity);

					ReportExplainFillEntity reportExplainFillEntity = new ReportExplainFillEntity();
					reportExplainFillEntity.setExplainCellDataId(CommonUtil.getUUID());
					reportExplainFillEntity.setAbsColNum(rs.getInt("ABS_COL_NUM") + "");
					reportExplainFillEntity.setAbsRowNum(rs.getInt("ABS_ROW_NUM") + "");
					reportExplainFillEntity.setExplainCellValue(explainCellValueId);
					reportExplainFillEntity.setDzzId(summaryDzzId);
					reportExplainFillEntity.setSumStatus("1");
					reportExplainFillEntity.setExplainId(rs.getString("EXPLAIN_ID"));
					reportExplainFillEntity.setIsSameRow(summaryDzzId);
					reportExplainDataMap.add(reportExplainFillEntity);
				}
				return null;
			}
		});
		try {
			dao.execute(sql);
		} catch (Exception e) {
			//reportExplainDataMap.add(null);
		}

	}

	class ReporExplainValueSummaryTread implements Callable<Map<Integer, Object>> {

		public List<String> treadExplainDzzIdList;
		public String annualId;
		public String dzzId;
		public String templateId;
		public List<ReportExplainFillEntity> reportExplainDataMap;
		public List<ReportExplainTextFillEntity> reportExplainTextDataMap;
		private boolean isSum;
		private HttpSession session;

		public ReporExplainValueSummaryTread(HttpSession session, List<String> treadExplainDzzIdList, String annualId,
				String dzzId, String templateId) {
			this.treadExplainDzzIdList = treadExplainDzzIdList;
			this.annualId = annualId;
			this.dzzId = dzzId;
			this.templateId = templateId;
			this.reportExplainDataMap = new ArrayList<ReportExplainFillEntity>();
			this.reportExplainTextDataMap = new ArrayList<ReportExplainTextFillEntity>();
			this.session = session;
		}

		@Override
		public Map<Integer, Object> call() throws Exception {
			List<String> explainIdTMList = new ArrayList<String>();
			List<String> explainIdSZList = new ArrayList<String>();
			List<String> explainIdWBList = new ArrayList<String>();
			//先根据报表ID获得所有报表说明
			List<RptTemplateExplain> explainTMList = reportTemplateExplainService
					.getAllExplainByTemplateAndType(templateId, "1");
			for (RptTemplateExplain rptTemplateExplain : explainTMList) {
				explainIdTMList.add(rptTemplateExplain.getId());
			}
			List<RptTemplateExplain> explainSZList = reportTemplateExplainService
					.getAllExplainByTemplateAndType(templateId, "2");
			for (RptTemplateExplain rptTemplateExplain : explainSZList) {
				explainIdSZList.add(rptTemplateExplain.getId());
			}
			List<RptTemplateExplain> explainWBList = reportTemplateExplainService
					.getAllExplainByTemplateAndType(templateId, "3");
			for (RptTemplateExplain rptTemplateExplain : explainWBList) {
				explainIdWBList.add(rptTemplateExplain.getId());
			}
			if(!explainIdTMList.isEmpty()) {
				rptCellExplainSummaryTiaoMu(treadExplainDzzIdList, explainIdTMList, annualId, dzzId, reportExplainDataMap);
			}
			if(!explainIdSZList.isEmpty()) {
				rptCellExplainSummaryShuZi(treadExplainDzzIdList, explainIdSZList, annualId, dzzId, reportExplainDataMap);
			}
			if(!explainIdWBList.isEmpty()) {
				rptCellExplainSummaryWenBen(treadExplainDzzIdList, explainIdWBList, annualId, dzzId, reportExplainDataMap,
						reportExplainTextDataMap);
			}

			Map<Integer, Object> result = new HashMap<Integer, Object>();
			result.put(1, reportExplainDataMap);
			result.put(2, reportExplainTextDataMap);

			if (session != null) {
				AtomicInteger counter = (AtomicInteger) session.getAttribute("generationCounter");
				counter.addAndGet(1);
				session = null;
			}
			logger.debug("------------------------------------->ReportSummaryNewService 报表说明数据汇总的一个线程结束了");
			return result;
		}

	}

}
